// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   Scanner.java

package MiniC.Scann;

import java.io.PrintStream;

// Referenced classes of package MiniC.Scanner:
//            SourcePos, Token, SourceFile

public final class Scanner
{

    private boolean isLetter(char c)
    {
        return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
    }

    private boolean isDigit(char c)
    {
        return c >= '0' && c <= '9';
    }

    public Scanner(SourceFile source)
    {
        sourceFile = source;
        currentChar = sourceFile.readChar();
        verbose = false;
        NrBufferedChars = 0;
        untakeBuffer = new char[10];
        currentLineNr = 1;
        currentColNr = 1;
    }

    public void enableDebugging()
    {
        verbose = true;
    }

    void BailOut(int nr)
    {
        untakeChar(currentChar);
        switch(nr)
        {
        case 3: // '\003'
            untakeChar(LookAhead3);
            currentLexeme.deleteCharAt(currentLexeme.length() - 1);
            // fall through

        case 2: // '\002'
            untakeChar(LookAhead2);
            currentLexeme.deleteCharAt(currentLexeme.length() - 1);
            // fall through

        case 1: // '\001'
            currentLexeme.deleteCharAt(currentLexeme.length() - 1);
            break;

        default:
            if(!$assertionsDisabled)
                throw new AssertionError();
            break;
        }
        currentChar = LookAhead1;
        currentColNr = currentColNr - nr;
    }

    void Delete()
    {
        currentLexeme.deleteCharAt(currentLexeme.length() - 1);
    }

    boolean ScanExponent()
    {
        if(currentChar != 'e' && currentChar != 'E')
            return false;
        LookAhead1 = currentChar;
        takeIt();
        if(currentChar == '+' || currentChar == '-')
        {
            LookAhead2 = currentChar;
            takeIt();
            if(!isDigit(currentChar))
            {
                BailOut(2);
                return false;
            }
        } else
        if(!isDigit(currentChar))
        {
            BailOut(1);
            return false;
        }
        do
            takeIt();
        while(isDigit(currentChar));
        return true;
    }

    private void takeIt()
    {
        if(currentlyScanningToken)
            currentLexeme.append(currentChar);
        if(currentChar == '\n')
        {
            currentLineNr++;
            currentColNr = 1;
        } else
        {
            currentColNr++;
        }
        if(NrBufferedChars > 0)
        {
            currentChar = untakeBuffer[NrBufferedChars - 1];
            NrBufferedChars--;
        } else
        {
            currentChar = sourceFile.readChar();
        }
    }

    private void untakeChar(char c)
    {
        if(NrBufferedChars == untakeBuffer.length)
        {
            System.out.println("Scanner error: untakeBuffer overflow!");
            System.exit(-1);
        }
        untakeBuffer[NrBufferedChars] = c;
        NrBufferedChars++;
    }

    private void scanWhitespace()
    {
        boolean oldSetting = currentlyScanningToken;
        currentlyScanningToken = false;
        while(currentChar == ' ' || currentChar == '\f' || currentChar == '\n' || currentChar == '\r' || currentChar == '\t') 
            takeIt();
        currentlyScanningToken = oldSetting;
    }

    private int scanToken()
    {
        switch(currentChar)
        {
        case 65: // 'A'
        case 66: // 'B'
        case 67: // 'C'
        case 68: // 'D'
        case 69: // 'E'
        case 70: // 'F'
        case 71: // 'G'
        case 72: // 'H'
        case 73: // 'I'
        case 74: // 'J'
        case 75: // 'K'
        case 76: // 'L'
        case 77: // 'M'
        case 78: // 'N'
        case 79: // 'O'
        case 80: // 'P'
        case 81: // 'Q'
        case 82: // 'R'
        case 83: // 'S'
        case 84: // 'T'
        case 85: // 'U'
        case 86: // 'V'
        case 87: // 'W'
        case 88: // 'X'
        case 89: // 'Y'
        case 90: // 'Z'
        case 95: // '_'
        case 97: // 'a'
        case 98: // 'b'
        case 99: // 'c'
        case 100: // 'd'
        case 101: // 'e'
        case 102: // 'f'
        case 103: // 'g'
        case 104: // 'h'
        case 105: // 'i'
        case 106: // 'j'
        case 107: // 'k'
        case 108: // 'l'
        case 109: // 'm'
        case 110: // 'n'
        case 111: // 'o'
        case 112: // 'p'
        case 113: // 'q'
        case 114: // 'r'
        case 115: // 's'
        case 116: // 't'
        case 117: // 'u'
        case 118: // 'v'
        case 119: // 'w'
        case 120: // 'x'
        case 121: // 'y'
        case 122: // 'z'
            takeIt();
            for(; isLetter(currentChar) || isDigit(currentChar) || currentChar == '_'; takeIt());
            return !currentLexeme.toString().equals("true") && !currentLexeme.toString().equals("false") ? 0 : 17;

        case 48: // '0'
        case 49: // '1'
        case 50: // '2'
        case 51: // '3'
        case 52: // '4'
        case 53: // '5'
        case 54: // '6'
        case 55: // '7'
        case 56: // '8'
        case 57: // '9'
            takeIt();
            for(; isDigit(currentChar); takeIt());
            if(currentChar == '.')
            {
                takeIt();
                for(; isDigit(currentChar); takeIt());
                ScanExponent();
                return 16;
            }
            return !ScanExponent() ? 15 : 16;

        case 46: // '.'
            takeIt();
            if(!isDigit(currentChar))
                return 36;
            do
                takeIt();
            while(isDigit(currentChar));
            ScanExponent();
            return 16;

        case 43: // '+'
            takeIt();
            return 11;

        case 45: // '-'
            takeIt();
            return 12;

        case 47: // '/'
            takeIt();
            return 14;

        case 61: // '='
            takeIt();
            if(currentChar == '=')
            {
                takeIt();
                return 5;
            } else
            {
                return 1;
            }

        case 59: // ';'
            takeIt();
            return 35;

        case 42: // '*'
            takeIt();
            return 13;

        case 34: // '"'
            currentlyScanningToken = false;
            takeIt();
            currentlyScanningToken = true;
            do
            {
                if(currentChar == '\n')
                    break;
                switch(currentChar)
                {
                case 92: // '\\'
                    takeIt();
                    if(currentChar != 'n')
                        System.out.println("ERROR: illegal escape sequence");
                    takeIt();
                    break;

                case 34: // '"'
                    currentlyScanningToken = false;
                    takeIt();
                    currentlyScanningToken = true;
                    return 18;

                default:
                    takeIt();
                    break;
                }
            } while(true);
            System.out.println("ERROR: unterminated string literal");
            return 18;

        case 124: // '|'
            takeIt();
            if(currentChar == '|')
            {
                takeIt();
                return 2;
            } else
            {
                return 36;
            }

        case 38: // '&'
            takeIt();
            if(currentChar == '&')
            {
                takeIt();
                return 3;
            } else
            {
                return 36;
            }

        case 33: // '!'
            takeIt();
            if(currentChar == '=')
            {
                takeIt();
                return 6;
            } else
            {
                return 4;
            }

        case 44: // ','
            takeIt();
            return 34;

        case 60: // '<'
            takeIt();
            if(currentChar == '=')
            {
                takeIt();
                return 7;
            } else
            {
                return 8;
            }

        case 62: // '>'
            takeIt();
            if(currentChar == '=')
            {
                takeIt();
                return 10;
            } else
            {
                return 9;
            }

        case 123: // '{'
            takeIt();
            return 28;

        case 125: // '}'
            takeIt();
            return 29;

        case 91: // '['
            takeIt();
            return 30;

        case 93: // ']'
            takeIt();
            return 31;

        case 40: // '('
            takeIt();
            return 32;

        case 41: // ')'
            takeIt();
            return 33;

        case 0: // '\0'
            return 37;

        case 1: // '\001'
        case 2: // '\002'
        case 3: // '\003'
        case 4: // '\004'
        case 5: // '\005'
        case 6: // '\006'
        case 7: // '\007'
        case 8: // '\b'
        case 9: // '\t'
        case 10: // '\n'
        case 11: // '\013'
        case 12: // '\f'
        case 13: // '\r'
        case 14: // '\016'
        case 15: // '\017'
        case 16: // '\020'
        case 17: // '\021'
        case 18: // '\022'
        case 19: // '\023'
        case 20: // '\024'
        case 21: // '\025'
        case 22: // '\026'
        case 23: // '\027'
        case 24: // '\030'
        case 25: // '\031'
        case 26: // '\032'
        case 27: // '\033'
        case 28: // '\034'
        case 29: // '\035'
        case 30: // '\036'
        case 31: // '\037'
        case 32: // ' '
        case 35: // '#'
        case 36: // '$'
        case 37: // '%'
        case 39: // '\''
        case 58: // ':'
        case 63: // '?'
        case 64: // '@'
        case 92: // '\\'
        case 94: // '^'
        case 96: // '`'
        default:
            takeIt();
            return 36;
        }
    }

    public Token scan()
    {
        currentlyScanningToken = true;
        currentLexeme = new StringBuffer("");
        boolean done = false;
        do
        {
            if(done)
                break;
            scanWhitespace();
            switch(currentChar)
            {
            case 47: // '/'
                takeIt();
                if(currentChar == '/')
                    while(currentChar != '\n') 
                        takeIt();
                else
                if(currentChar == '*')
                {
                    takeIt();
                    do
                    {
                        if(currentChar == 0)
                            break;
                        if(currentChar == '*')
                        {
                            takeIt();
                            if(currentChar != '/')
                                continue;
                            takeIt();
                            break;
                        }
                        takeIt();
                    } while(true);
                    if(currentChar == 0)
                    {
                        System.out.println("ERROR: unterminated multi-line comment.");
                        done = true;
                    }
                } else
                {
                    LookAhead1 = '/';
                    BailOut(1);
                    done = true;
                }
                break;

            default:
                done = true;
                break;
            }
        } while(true);
        currentlyScanningToken = true;
        currentLexeme = new StringBuffer("");
        SourcePos pos = new SourcePos();
        pos.StartLine = currentLineNr;
        pos.EndLine = currentLineNr;
        pos.StartCol = currentColNr;
        int kind = scanToken();
        if(kind == 37)
        {
            pos.EndCol = currentColNr;
            currentLexeme.append('$');
        } else
        {
            pos.EndCol = currentColNr - 1;
        }
        Token currentToken = new Token(kind, currentLexeme.toString(), pos);
        if(verbose)
            currentToken.print();
        return currentToken;
    }

    static Class _mthclass$(String x0) throws Throwable
    {
        try
        {
            return Class.forName(x0);
        }
        catch(ClassNotFoundException x1)
        {
            throw (new NoClassDefFoundError()).initCause(x1);
        }
    }

    private SourceFile sourceFile;
    private char currentChar;
    private boolean verbose;
    private StringBuffer currentLexeme;
    private boolean currentlyScanningToken;
    private int NrBufferedChars;
    private char untakeBuffer[];
    private int currentLineNr;
    private int currentColNr;
    private char LookAhead1;
    private char LookAhead2;
    private char LookAhead3;
    static final boolean $assertionsDisabled; /* synthetic field */

    static 
    {
        $assertionsDisabled = !(MiniC.Scann.Scanner.class).desiredAssertionStatus();
    }
}
